import org.zkoss.zk.ui.Component;
import org.zkoss.zul.api.Button;
import org.zkoss.zul.api.Textbox;
import org.zkoss.zul.api.Label;

public class CalculatorController extends Listbox{
	
	private double currentShow = 0;
	private String currentShowString = "0";
	private int currentInput = 0;
	private boolean isLastInputDigit = true;
	private boolean isMemoryOn = false;
	private double memoryResult = 0;
	private boolean hasOperator = false;
	private char currentOperator = '0';
	private double operateNum1 = 0,operateNum2 = 0;
	private boolean isResult = false;
	private boolean isLastInputReciproc = false;
	private double lastReciproc = 0;
	private Textbox resultBox;
	static private int MAXDIGIT = 16;
	
	public void initialize(){
		this.showResult();
	}
	
	public void getCurrentShow(){
		resultBox = (Textbox)getFellow("RESULT_AREA");
		currentShowString = resultBox.getText();
		currentShow = Double.parseDouble(currentShowString);
	}
	
	public void numEventHandler(Component comp){
		this.getCurrentShow();
		if(currentShowString.length() >= MAXDIGIT)
			return;
		currentInput = comp.getId().charAt(comp.getId().length()-1)-48;
		if (isResult||"0".equals(currentShowString))
		{
			currentShowString = ""+currentInput;
			currentShow = Double.parseDouble(currentShowString);
			isResult = false;
		}
		else
		{
			currentShowString += ""+currentInput;
			currentShow = Double.parseDouble(currentShowString);
		}
		this.showResult();
		currentInput = 0;
		isLastInputDigit = true;
	}
	
	public void dotEventHandler(){
		if (isResult)
		{
			currentShowString = "0.";
			currentShow = 0;
		}
		else
		{
			this.getCurrentShow();
			if (currentShowString.indexOf(".") == -1)
				currentShowString += ".";
		}
		this.showResult();
	}
	
	public double doCalculation(char operator,double num1,double num2){
		double result = 0;
		switch(operator)
		{
		case 'A':
			result = num1 + num2;
			break;
		case 'S':
			result = num1 - num2;
			break;
		case 'M':
			result = num1 * num2;
			break;
		case 'D':
			result = num1 / num2;
			break;
		}
		return result;
	}
	
	public void operatorEventHandler(Component comp){
		if (!hasOperator)
		{
			operateNum1 = currentShow;
			currentOperator = comp.getId().charAt(comp.getId().length()-1);
			hasOperator = true;
		}
		else
		{
			if (!isLastInputDigit)
			{
				currentOperator = comp.getId().charAt(comp.getId().length()-1);
				return;
			}
			operateNum2 = currentShow;
			if (currentOperator == 'D' && operateNum2 == 0)
			{
				this.clearAll();
				return;
			}
			operateNum1 = this.doCalculation(currentOperator, operateNum1, operateNum2);
			currentOperator = comp.getId().charAt(comp.getId().length()-1);
			currentShow = operateNum1;
			currentShowString = ""+currentShow;
		}
		this.showResult();
		isResult = true;
		isLastInputDigit = false;
	}
	
	public void equalEventHandler(){
		this.getCurrentShow();
		if (!hasOperator)
		{
			isResult = true;
			this.showResult();
			return;
		}
		else
		{
			if (!isLastInputDigit)
				operateNum1 = this.doCalculation(currentOperator, operateNum1, operateNum1);
			else
			{
				operateNum2 = currentShow;
				if (currentOperator == 'D' && operateNum2 == 0)
				{
					operateNum1 = 0;
				}
				else
					operateNum1 = this.doCalculation(currentOperator, operateNum1, operateNum2);
			}
		}
		currentShow = operateNum1;
		currentShowString = ""+currentShow;
		this.showResult();
		isResult = true;
		isLastInputDigit = false;
		hasOperator = false;
	}
	
	public void radical(){
		this.getCurrentShow();
		currentShow = Math.sqrt(currentShow);
		currentShowString = ""+currentShow;
		
		this.showResult();
		isResult = true;
	}
	
	public void percent(){
		if (!hasOperator)
		{
			currentShowString = "0";
			currentShow = 0;
		}
		else
		{
			if (!isLastInputDigit)
			{
				operateNum2 = operateNum1 * 0.01;
			}
			else
			{
				operateNum2 = operateNum1 * 0.01 * operateNum2;
			}
			currentShowString = ""+operateNum2;
			currentShow = operateNum2;
			isResult = true;
			isLastInputDigit = true;
		}
		this.showResult();
	}
	
	public void reciproc(){
		this.getCurrentShow();
		if (currentShow == 0)
		{
			this.clearAll();
			return;
		}
		else
		{
			if (isLastInputReciproc)
			{
				currentShow = lastReciproc;
				currentShowString = ""+currentShow;
				lastReciproc = 1/currentShow;
			}
			else
			{
				lastReciproc = currentShow;
				currentShow = 1/currentShow;
				currentShowString = ""+currentShow;
				isLastInputReciproc = true;
			}
		}
		this.showResult();
		isResult = true;
	}
	
	public void negative(){
		this.getCurrentShow();
		if (currentShow < 0)
			currentShowString = currentShowString.substring(1,currentShowString.length());
		else
			currentShowString = "-"+currentShowString;
		
		currentShow = Double.parseDouble(currentShowString);
		this.showResult();
	}
	
	public void backspace(){
		this.getCurrentShow();
		if ("0".equals(currentShowString))
			return;
		else if (currentShowString.length()==1)
		{
			currentShowString = "0";
			currentShow = 0;
			this.showResult();
			return;
		}
		currentShowString = currentShowString.substring(0,currentShowString.length()-1);
		currentShow = Double.parseDouble(currentShowString);
		this.showResult();
	}
	
	public void clearCurrentShow(){
		this.getCurrentShow();
		currentShow = 0;
		currentShowString = "0";
		this.showResult();
	}
	
	public void clearAll(){
		this.getCurrentShow();
		currentResult = 0;
		currentResultString = "0";
		currentShow = 0;
		currentShowString = "0";
		isResult = true;
		isMemoryOn = false;
		isLastInputDigit = true;
		hasOperator = false;
		this.showResult();
	}
	
	public void memoryClear(){
		memoryResult = 0;
		isMemoryOn = false;
		isResult = true;
	}
	
	public void memoryRecord(){
		currentShow = memoryResult;
		currentShowString = ""+currentShow;
		this.showResult();
		isResult = true;
		isLastInputDigit = true;
	}
	
	public void memorySave(){
		memoryResult = currentShow;
		isResult = true;
	}
	
	public void memoryAdd(){
		memoryResult += currentShow;
		isResult = true;
	}
	
	public void memorySubtract(){
		memoryResult -= currentShow;
		isResult = true;
	}

	public void showResult(){
		if (currentShowString.length() > MAXDIGIT)
		{
			if (currentShowString.charAt(0) == '-')
			{	
				if (currentShowString.charAt(MAXDIGIT)-48 > 4)
					currentShowString = currentShowString.substring(0,MAXDIGIT)+(currentShowString.charAt(MAXDIGIT)-47);
				else
					currentShowString = currentShowString.substring(0,MAXDIGIT+1);
			}
			else
			{
				if (currentShowString.charAt(MAXDIGIT-1)-48 > 4)
					currentShowString = currentShowString.substring(0,MAXDIGIT-1)+(currentShowString.charAt(MAXDIGIT-1)-47);
				else
					currentShowString = currentShowString.substring(0,MAXDIGIT);
			}
		}
		int index = currentShowString.indexOf(".");
		if (index != -1 && index == currentShowString.length()-2 && currentShowString.charAt(currentShowString.length()-1) == '0')
			currentShowString = currentShowString.substring(0,currentShowString.length()-2);
	
		resultBox = (Textbox)getFellow("RESULT_AREA");
		resultBox.setText(currentShowString);
	}
}
